import { Mars3DRender } from './Mars3dRender.jsx'
const { mars3d } = window
const CommonSceneUrl = {
    forge: 'https://image.ljkjkf.com/intellisiteSystem_TieKe/Scene/forge/',
    gltf: 'https://image.ljkjkf.com/intellisiteSystem_TieKe/Scene/gltf/',
    img: 'https://image.ljkjkf.com/intellisiteSystem_TieKe/Scene/img/',
    json: 'https://image.ljkjkf.com/intellisiteSystem_TieKe/Scene/json/',
    kml: 'https://image.ljkjkf.com/intellisiteSystem_TieKe/Scene/kml/',
    other: 'https://image.ljkjkf.com/intellisiteSystem_TieKe/Scene/other/',
    tiles: 'https://image.ljkjkf.com/intellisiteSystem_TieKe/Scene/tiles/',
}

const specialMap = [120000, 150000, 340000]

const basemapsList = [
    // 影像
    {
        id: 'BaseD01',
        name: '谷歌影像',
        type: 'google',
        layer: 'img_d',
    },
    {
        id: 'BaseD02',
        name: '微软影像',
        type: 'bing',
        layer: 'Aerial',
    },
    {
        id: 'BaseD03',
        name: 'ArcGIS影像',
        type: 'xyz',
        url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
        enablePickFeatures: false,
    },
    {
        id: 'BaseD04',
        name: '天地图影像',
        type: 'tdt',
        layer: 'img_d',
    },
    {
        id: 'BaseD05',
        name: '高德影像',
        type: 'gaode',
        layer: 'img_d',
    },
    {
        id: 'BaseD06',
        name: '百度影像',
        type: 'baidu',
        layer: 'img_d',
    },
    {
        id: 'BaseD07',
        name: '腾讯影像',
        type: 'tencent',
        layer: 'img_d',
    },
    // 电子图
    {
        id: 'BaseV01',
        name: '蓝色底图',
        type: 'xyz',
        url: 'http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}',
        chinaCRS: 'GCJ02',
        enablePickFeatures: false,
    },
    {
        id: 'BaseV02',
        name: '黑色底图',
        type: 'tencent',
        layer: 'custom',
        style: '4',
    },
    {
        id: 'BaseV03',
        name: '暗色底图',
        type: 'gaode',
        layer: 'vec',
        invertColor: true,
        filterColor: '#4e70a6',
        brightness: 0.6,
        contrast: 1.8,
        gamma: 0.3,
        hue: 1,
        saturation: 0,
    },
    {
        id: 'BaseV04',
        name: '天地图电子',
        type: 'group',
        layers: [
            { name: '底图', type: 'tdt', layer: 'vec_d' },
            { name: '注记', type: 'tdt', layer: 'vec_z' },
        ],
    },
    {
        id: 'BaseV05',
        name: '高德电子',
        type: 'gaode',
        layer: 'vec',
    },
    {
        id: 'BaseV06',
        name: '百度电子',
        type: 'baidu',
        layer: 'vec',
    },
    {
        id: 'BaseV07',
        name: '腾讯电子',
        type: 'tencent',
        layer: 'vec',
    },
]

const layerList = [
    {
        id: 'BaseZ01',
        name: '谷歌注记',
        type: 'google',
        layer: 'img_z',
        show: false,
    },
    {
        id: 'BaseZ04',
        name: '天地图注记',
        type: 'tdt',
        layer: 'img_z',
        show: false,
    },
    {
        id: 'BaseZ05',
        name: '高德注记',
        type: 'gaode',
        layer: 'img_z',
        show: false,
    },
    {
        id: 'BaseZ06',
        name: '百度注记',
        type: 'baidu',
        layer: 'img_z',
        show: false,
    },
    {
        id: 'BaseZ07',
        name: '腾讯注记',
        type: 'tencent',
        layer: 'img_z',
        show: false,
    },
    {
        id: 'LayF01',
        mapSplit: false,
        maximumLevel: 10,
        name: '行政区划界线',
        type: 'tdt',
        url: 'https://t{s}.tianditu.gov.cn/DataServer?T=ibo_w&x={x}&y={y}&l={z}',
        show: false,
    },
    {
        id: 'LayF02',
        name: '经纬网',
        type: 'graticule',
        show: false,
    },
    {
        id: 'LayF03',
        name: '夜晚图片',
        type: 'image',
        url: CommonSceneUrl.img + 'night2.jpg',
        dayAlpha: 0.0,
        nightAlpha: 1.0,
        brightness: 3.5,
    },
    {
        id: 'LayF04',
        name: '网格线',
        type: 'grid',
        color: '#ffffff',
        alpha: 0.03,
        cells: 2,
        show: false,
    },
]

// 地球初始化
const initData = {
    scene: {
        center: { lat: 29.662791, lng: 112.138623, alt: 7205398.9, heading: 355.6, pitch: -88.1 },
        orderIndependentTranslucency: false,
        contextOptions: { webgl: { alpha: true } },
    },
    control: {
        homeButton: true,
        zoom: true,
        fullscreenButton: true,
        geocoder: 'gaode',
        baseLayerPicker: false,
        locationBar: true,
        distanceLegend: true,
        compass: { top: '16px', left: '16px' },
    },
    basemaps: basemapsList,
    layers: layerList,
    terrain: { url: '//data.mars3d.cn/terrain', show: true },
    templateValues: {
        dataServer: 'http://data.mars3d.cn',
        gltfServerUrl: 'http://data.mars3d.cn/gltf',
    },
}

// 初始化mars函数element
export const Initialization = (DIV, config, data) => {
    const map = new mars3d.Map(DIV, initData)
    const gra = new mars3d.layer.GraphicLayer({ isEditing: true })
    const clip = new mars3d.thing.TerrainClip({ czm: false })
    effectOn(map)
    map.addLayer(gra)
    map.addThing(clip)
    SetConfig(map, gra, clip, config)
    data && Mars3DRender({ map, gra, clip, data })
    return { map, gra, clip }
}

export const SetConfig = (map, gra, clip, config) => {
    InitFitA01(map, config.FitA01)
    InitFitA02(map, config.FitA02)
    InitFitA03(map, config.FitA03)
    InitFitA04(map, config.FitA04)
    InitFitA05(map, config.FitA05)
    InitFitA06(map, config.FitA06)
    InitFitA07(gra, clip, config.FitA07)
    InitOthA01(map, config.OthA01)
}

// 初始化基础图层
const InitFitA01 = (map, params) => {
    map.setSceneOptions(params)
}

const InitFitA02 = (map, params) => {
    map.setSceneOptions({ globe: params })
}

const InitFitA03 = (map, params) => {
    map.basemap = params.basemap
    map.setLayersOptions(LayerListMap(params.layer))
    map.setSceneOptions({ globe: { baseColor: params.baseColor } })
}
// 遍历辅助图层
export const LayerListMap = arr => {
    return layerList.map(item => {
        const isItemInValue = arr.includes(item.id)
        const show = isItemInValue ? true : false
        return { ...item, show }
    })
}

const InitFitA04 = (map, params) => {
    map.setSceneOptions({ cameraController: params })
}

const InitFitA05 = (map, params) => {
    Object.keys(params).forEach(key => (map.controls[key].show = params[key]))
}

const InitFitA06 = (map, params) => {
    map.effects.nightVision.enabled = params.nightVisionEffect
    map.effects.mosaic.enabled = params.mosaicEffect
    map.effects.blackAndWhite.enabled = params.blackAndWhiteEffect
    map.effects.blackAndWhite.gradations = params.gradations

    map.effects.depthOfField.enabled = params.depthOfField
    map.effects.depthOfField.focalDistance = params.depthFocalDistance
    map.effects.depthOfField.delta = params.depthDelta
    map.effects.depthOfField.sigma = params.depthSigma
    map.effects.depthOfField.stepSize = params.depthStepSize

    map.effects.bloom.enabled = params.bloomEffect
    map.effects.bloom.contrast = params.bloomContrast
    map.effects.bloom.brightness = params.bloomBrightness
    map.effects.bloom.delta = params.bloomDelta
    map.effects.bloom.sigma = params.bloomSigma
    map.effects.bloom.stepSize = params.bloomStepSize

    map.effects.brightness.enabled = params.brightnessEffect
    map.effects.brightness.brightness = params.brightness

    map.effects.fog.enabled = params.fogEffect
    map.effects.fog.fogByDistance.x = params.fogByDistance_near
    map.effects.fog.fogByDistance.z = params.fogByDistance_far
    map.effects.fog.maxHeight = params.fogMaxHeight

    map.effects.rain.enabled = params.rainEffect
    map.effects.rain.size = params.rainSize
    map.effects.rain.speed = params.rainSpeed
    map.effects.rain.direction = params.rainDirection

    map.effects.snow.enabled = params.snowEffect
    map.effects.snow.speed = params.snowSpeed
    map.effects.snow.maxHeight = params.snowMaxHeight

    map.effects.snowCover.enabled = params.snowCover
    map.effects.snowCover.alpha = params.snowCoverAlpha
    map.effects.snowCover.maxHeight = params.snowCoverMaxHeight

    map.effects.outline.enabled = params.outlineEffect
    map.effects.outline.color = params.outlineColor
    map.effects.outline.colorHidden = params.outlineColorHidden
    map.effects.outline.width = params.outlineWidth
    map.effects.outline.showPlane = params.outlineShowPlane
    map.effects.outline.planeAngle = params.outlinePlaneAngle
    map.effects.outline.glow = params.outlineGlow
    map.effects.outline.glowPower = params.outlineGlowPower
    map.effects.outline.glowStrength = params.outlineGlowStrength

    map.effects.bloomTarget.enabled = params.bloomTargetEffect
    map.effects.bloomTarget.color = params.bloomTargetColor
    map.effects.bloomTarget.brightness = params.bloomTargetBrightness
    map.effects.bloomTarget.ratio = params.bloomTargetRatio
    map.effects.bloomTarget.smoothWidth = params.bloomTargetSmoothWidth
    map.effects.bloomTarget.threshole = params.bloomTargetThreshole
    map.effects.bloomTarget.contrast = params.bloomTargetContrast
    map.effects.bloomTarget.blurSamples = params.bloomTargetBlurSamples
    map.effects.bloomTarget.stepSize = params.bloomTargetStepSize
    map.effects.bloomTarget.delta = params.bloomTargetDelta
    map.effects.bloomTarget.sigma = params.bloomTargetSigma
}

const InitFitA07 = (gra, clip, params) => {
    ClearGra(gra, clip)
    const { mapTiles, isClip, cove, line, wall } = params
    mapTiles.length !== 0 &&
        mapTiles.forEach(item => {
            GetUrlData(item).then(res => {
                const arr = mars3d.Util.geoJsonToGraphics(res)
                clipFunc(arr, isClip, clip)
                coveFunc(arr, cove, gra)
                lineFunc(arr, line, gra)
                wallFunc(arr, wall, gra)
            })
        })
}

const clipFunc = (arr, isClip, clip) => {
    if (isClip) {
        arr.forEach(({ attr, positions }) => {
            setTimeout(() => {
                if (specialMap.includes(attr.adcode)) {
                    positions.forEach(key => {
                        clip.addArea(key)
                        clip.clipOutSide = true
                    })
                } else {
                    clip.addArea(positions)
                    clip.clipOutSide = true
                }
            }, 1)
        })
    } else {
        clip.clear()
    }
}

const coveFunc = (arr, cove, gra) => {
    const { isEnabled, ...style } = cove
    if (isEnabled) {
        const renderDemo = positions => {
            const graphic = new mars3d.graphic.PolygonPrimitive({ positions, attr: 'Coverage', style })
            gra.addGraphic(graphic)
        }

        arr.forEach(({ attr, positions }) => {
            if (specialMap.includes(attr.adcode)) positions.forEach(key => renderDemo(key))
            else renderDemo(positions)
        })
    }
}
const lineFunc = (arr, line, gra) => {
    const { isEnabled, ...style } = line
    if (isEnabled) {
        const renderDemo = positions => {
            const polyline = new mars3d.graphic.PolylineEntity({ attr: 'BoundaryLine', positions, style })
            gra.addGraphic(polyline)
        }
        arr.forEach(({ attr, positions }) => {
            if (specialMap.includes(attr.adcode)) positions.forEach(key => renderDemo(key))
            else renderDemo(positions)
        })
    }
}
const wallFunc = (arr, wall, gra) => {
    const { isEnabled, ...style } = wall
    if (isEnabled) {
        const renderDemo = positions => {
            const Wall = new mars3d.graphic.WallPrimitive({ attr: 'BoundaryWall', positions, style })
            gra.addGraphic(Wall)
        }
        arr.forEach(({ attr, positions }) => {
            if (specialMap.includes(attr.adcode)) positions.forEach(key => renderDemo(key))
            else renderDemo(positions)
        })
    }
}

const ClearGra = (gra, clip) => {
    clip.clear()
    ClearBaseFunc(gra, 'Coverage')
    ClearBaseFunc(gra, 'BoundaryLine')
    ClearBaseFunc(gra, 'BoundaryWall')
}

const ClearBaseFunc = (Gra, value) => {
    const LineData = Gra.getGraphicsByAttr(value, 'attr')
    if (LineData.length !== 0) LineData.forEach(item => Gra.removeGraphic(item))
}

const InitOthA01 = (map, params) => {
    const { defaultCenter, centerList } = params
    if (defaultCenter) map.centerAt(centerList[defaultCenter].center)
}

// 初始化场景特效
const effectOn = map => {
    map.addEffect(new mars3d.effect.FogEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.RainEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.SnowEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.SnowCoverEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.BloomEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.BrightnessEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.NightVisionEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.BlackAndWhiteEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.MosaicEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.DepthOfFieldEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.OutlineEffect({ enabled: false }))
    map.addEffect(new mars3d.effect.BloomTargetEffect({ enabled: false }))
}

const GetUrlData = async url => {
    return await mars3d.Util.fetchJson({ url: CommonSceneUrl.json + url + '.json' })
}
